import { exportExcel } from "@/utils/ExcelHelper";
import SparkMD5 from "spark-md5";
const api = {
    //导出excel处理信息操作
    async exportsExcel(payload,id) {
        let {data,base64,excelOpt} = payload;
        data = JSON.parse(data);
        excelOpt = JSON.parse(excelOpt);
        data.map(item=>item.buffer = base64);
        excelOpt.sheetInfos[0]['data'] = data;
        excelOpt.sheetInfos.map(item => {
            item.attrs.push({
                rowStart: 0,
                rowEnd: item.headers?.length - 1,
                colStart: 0,
                colEnd: item.headers[0].length - 1,
                attr: {
                    fill: {
                        type: "pattern",
                        pattern: "solid",
                        fgColor: { argb: "99CCFF" }
                    },
                    font: {
                        bold: true
                    }
                }
            })

            //图片那一列单独增加高度设置
            item.attrs.push({
                rowStart: 1,
                rowEnd: item.headers?.length - 1,
                colStart: 2,
                colEnd: 3,
                attr: {
                    height: 80,
                }
            })
        })
        let exports = await exportExcel(excelOpt);
        this.worker.postMessage({id,response:exports});
    },
    testWorker(payload) {
        return Math.pow(payload, 2) + "数据计算完了"
    },
    //用来处理文件上传切面md5加密计算的方法
    computedMD5(fileItem,id){
        let md5Obj = {};//定义要返回的数据对象信息内容
        //定义获取文件对象的内容信息
        let file = fileItem.file;
        //获取file对象的slice方法并兼容各个浏览器
        let blobSize = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
        //文件大小相关信息
        let fileSize = file.size;
        //每个分片的大小 50M先设置，后续可以在修改，主要是针对大文件，如果比较小的文件直接生成md5即可
        let chunkSize = 1024*1024*50;
        //文件切片的个数
        let chunks = Math.ceil(fileSize/chunkSize);
        //定义当前读取到第一个切片默认从0开始
        let currentChunkIndex = 0;
        //spark对象信息
        let spark = new SparkMD5.ArrayBuffer();
        //文件读取对象切割处理
        let fileReader = new FileReader();
        let loadNext = ()=>{
            //切片开始的地方,类似于分页
            let start = currentChunkIndex*chunkSize;
            //切割结束点
            let end = start+chunkSize>fileSize ? fileSize : start+chunkSize;
            //读取文件加入到fileReader的缓存中去
            fileReader.readAsArrayBuffer(blobSize.call(file,start,end));
        }
        let startTime = Date.now();
        loadNext();//执行一次先处理操作
        //文件加载方法
        fileReader.onload = (e)=>{
            //把读取成功的文件切片，放到spark中进行加密
            spark.append(e.target.result);
            currentChunkIndex++;
            //小于切片的个数继续进行切片
            if(currentChunkIndex<chunks){
                console.log("开始切片")
                let precent = Math.floor(currentChunkIndex/chunks*100);
                Object.assign(md5Obj,{precent});
                // console.log(this.worker.hasOwnProperty("postMessage"));
                this.worker.postMessage({id,response:md5Obj})
                loadNext();//继续加一次切片处理
            }else{
                let endTime = Date.now();
                
                let md5 = spark.end();//计算后的md5的值
                spark.destroy();//销毁
                console.log(`切片结束,时间${endTime-startTime}ms`);
                Object.assign(md5Obj,{md5,precent:100})
                this.worker.postMessage({id,response:md5Obj});
                loadNext = null;
                this.worker.close();//关闭线程信息
            }
        }
        //文件加载读取失败的情况
        fileReader.onerror = ()=>{
            console.log(e,"文件读取出错");
            self.close();
            loadNext = null;
        }

        // return md5Obj;
    }
}

//worker线程操作信息
class WorkerThread {
    constructor() {
        //this赋值对象
        this.worker = self;
        //等待回调的基本逻辑
        this.actionHandlerMap = {};
        //调用onmessage方法
        this.worker.onmessage = this.onmessage.bind(this);
    }

    //封装onmessage方法
    async onmessage(e) {
        //接受传递过来的核心数据内容
        let { id, actionType, payload } = e.data;

        console.log(payload,"接受主线程数据");
        // return false;

        //根据传递过来的方法类型调用不同的逻辑对象
        api[actionType].call(this, payload,id);
        // 根据处理的数据结果，返回数据给主线程
        // this.worker.postMessage({ id, response: res })
    }
}

const workerThread = new WorkerThread();
